1300 #include "types.h"
1301 #include "defs.h"
1302 #include "param.h"
1303 #include "mmu.h"
1304 #include "proc.h"
1305 #include "x86.h"
1306 
1307 static void bootothers(void);
1308 static void mpmain(void);
1309 void jkstack(void)  __attribute__((noreturn));
1310 void mainc(void);
1311 
1312 // Bootstrap processor starts running C code here.
1313 int
1314 main(void)
1315 {
1316   mpinit();        // collect info about this machine
1317   lapicinit(mpbcpu());
1318   ksegment();      // set up segments
1319   picinit();       // interrupt controller
1320   ioapicinit();    // another interrupt controller
1321   consoleinit();   // I/O devices & their interrupts
1322   uartinit();      // serial port
1323   kinit();         // initialize memory allocator
1324   jkstack();       // call mainc() on a properly-allocated stack
1325 }
1326 
1327 void
1328 jkstack(void)
1329 {
1330   char *kstack = kalloc();
1331   if(!kstack)
1332     panic("jkstack\n");
1333   char *top = kstack + PGSIZE;
1334   asm volatile("movl %0,%%esp" : : "r" (top));
1335   asm volatile("call mainc");
1336   panic("jkstack");
1337 }
1338 
1339 
1340 
1341 
1342 
1343 
1344 
1345 
1346 
1347 
1348 
1349 
1350 void
1351 mainc(void)
1352 {
1353   cprintf("\ncpu%d: starting xv6\n\n", cpu->id);
1354   kvmalloc();      // initialize the kernel page table
1355   pinit();         // process table
1356   tvinit();        // trap vectors
1357   binit();         // buffer cache
1358   fileinit();      // file table
1359   iinit();         // inode cache
1360   ideinit();       // disk
1361   if(!ismp)
1362     timerinit();   // uniprocessor timer
1363   userinit();      // first user process
1364   bootothers();    // start other processors
1365 
1366   // Finish setting up this processor in mpmain.
1367   mpmain();
1368 }
1369 
1370 // Common CPU setup code.
1371 // Bootstrap CPU comes here from mainc().
1372 // Other CPUs jump here from bootother.S.
1373 static void
1374 mpmain(void)
1375 {
1376   if(cpunum() != mpbcpu()) {
1377     ksegment();
1378     lapicinit(cpunum());
1379   }
1380   vmenable();        // turn on paging
1381   cprintf("cpu%d: starting\n", cpu->id);
1382   idtinit();       // load idt register
1383   xchg(&cpu->booted, 1);
1384   scheduler();     // start running processes
1385 }
1386 
1387 
1388 
1389 
1390 
1391 
1392 
1393 
1394 
1395 
1396 
1397 
1398 
1399 
1400 static void
1401 bootothers(void)
1402 {
1403   extern uchar _binary_bootother_start[], _binary_bootother_size[];
1404   uchar *code;
1405   struct cpu *c;
1406   char *stack;
1407 
1408   // Write bootstrap code to unused memory at 0x7000.  The linker has
1409   // placed the start of bootother.S there.
1410   code = (uchar *) 0x7000;
1411   memmove(code, _binary_bootother_start, (uint)_binary_bootother_size);
1412 
1413   for(c = cpus; c < cpus+ncpu; c++){
1414     if(c == cpus+cpunum())  // We've started already.
1415       continue;
1416 
1417     // Fill in %esp, %eip and start code on cpu.
1418     stack = kalloc();
1419     *(void**)(code-4) = stack + KSTACKSIZE;
1420     *(void**)(code-8) = mpmain;
1421     lapicstartap(c->id, (uint)code);
1422 
1423     // Wait for cpu to finish mpmain()
1424     while(c->booted == 0)
1425       ;
1426   }
1427 }
1428 
1429 
1430 
1431 
1432 
1433 
1434 
1435 
1436 
1437 
1438 
1439 
1440 
1441 
1442 
1443 
1444 
1445 
1446 
1447 
1448 
1449 
